#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Technical Update Word模板处理脚本
功能：将技术更新数据写入Word模板的第一个表格中
"""

# 重定向所有可能的输出到stderr，确保stdout只用于最终JSON结果
import sys
import json
import os

# 设置环境变量确保UTF-8编码
os.environ['PYTHONIOENCODING'] = 'utf-8'
from datetime import datetime
from pathlib import Path

# 捕获所有导入过程中可能的输出
try:
    from docx import Document
    from docx.shared import Inches, RGBColor
    from docx.enum.text import WD_ALIGN_PARAGRAPH
    import docx.oxml.shared
    import docx.opc.constants
except ImportError as e:
    print(f"错误：缺少python-docx库，请安装：pip install python-docx. 详细错误: {e}", file=sys.stderr)
    sys.stderr.flush()
    sys.exit(1)
except Exception as e:
    print(f"导入模块时发生错误: {e}", file=sys.stderr)
    sys.stderr.flush()
    sys.exit(1)

def log_message(message, level="INFO"):
    """输出日志信息并返回格式化的日志文本"""
    timestamp = datetime.now().strftime("%H:%M:%S")
    log_text = f"[{timestamp}] [{level}] {message}"
    # 确保日志只输出到stderr，不影响stdout的JSON输出
    try:
        print(log_text, file=sys.stderr)
        sys.stderr.flush()  # 确保立即输出
    except Exception:
        # 如果stderr输出失败，静默处理，不影响主要功能
        pass
    return log_text  # 返回日志文本供JS端使用

def add_hyperlink(paragraph, url, text, color='#0000FF'):
    """在段落中添加超链接
    
    Args:
        paragraph: 段落对象
        url: 链接地址
        text: 显示文本
        color: 链接颜色，默认蓝色
    
    Returns:
        hyperlink元素
    """
    if not url or not text:
        # 如果URL或文本为空，只添加普通文本
        run = paragraph.add_run(text)
        return run
    
    try:
        # 获取文档部分并创建关系ID
        part = paragraph.part
        r_id = part.relate_to(url, docx.opc.constants.RELATIONSHIP_TYPE.HYPERLINK, is_external=True)
        
        # 创建超链接元素
        hyperlink = docx.oxml.shared.OxmlElement('w:hyperlink')
        hyperlink.set(docx.oxml.shared.qn('r:id'), r_id)
        
        # 创建运行元素
        new_run = docx.oxml.shared.OxmlElement('w:r')
        rPr = docx.oxml.shared.OxmlElement('w:rPr')
        
        # 设置颜色
        if color:
            c = docx.oxml.shared.OxmlElement('w:color')
            c.set(docx.oxml.shared.qn('w:val'), color.replace('#', ''))
            rPr.append(c)
        
        # 设置下划线
        u = docx.oxml.shared.OxmlElement('w:u')
        u.set(docx.oxml.shared.qn('w:val'), 'single')
        rPr.append(u)
        
        new_run.append(rPr)
        new_run.text = text
        hyperlink.append(new_run)
        
        # 将超链接添加到段落
        paragraph._p.append(hyperlink)
        
        return hyperlink
    except Exception as e:
        # 如果创建超链接失败，添加普通文本
        run = paragraph.add_run(text)
        return run

def process_tech_update_data(data_input):
    """
    处理技术更新数据并写入Word模板
    
    Args:
        data_input (str): JSON格式的数据字符串或JSON文件路径
    
    Returns:
        dict: 处理结果
    """
    logs = []  # 收集所有日志信息
    
    try:
        # 解析输入数据
        logs.append(log_message("开始解析输入数据..."))
        logs.append(log_message(f"输入数据类型: {type(data_input)}"))
        logs.append(log_message(f"输入数据长度: {len(str(data_input))}"))
        
        # 判断输入是文件路径还是JSON字符串
        if os.path.isfile(data_input):
            logs.append(log_message(f"从文件读取数据: {data_input}"))
            try:
                with open(data_input, 'r', encoding='utf-8') as f:
                    file_content = f.read()
                    logs.append(log_message(f"文件内容长度: {len(file_content)}"))
                    # logs.append(log_message(f"文件内容前100字符: {file_content[:100]}"))
                    data_dict = json.loads(file_content)
                # 读取完成后删除临时文件
                try:
                    os.remove(data_input)
                    logs.append(log_message(f"已删除临时文件: {data_input}"))
                except Exception as e:
                    logs.append(log_message(f"删除临时文件失败: {e}", "WARNING"))
            except json.JSONDecodeError as je:
                logs.append(log_message(f"文件JSON解析失败: {je}", "ERROR"))
                raise
            except Exception as fe:
                logs.append(log_message(f"文件读取失败: {fe}", "ERROR"))
                raise
        else:
            logs.append(log_message("直接解析JSON字符串"))
            logs.append(log_message(f"JSON字符串前100字符: {str(data_input)[:100]}"))
            try:
                data_dict = json.loads(data_input)
            except json.JSONDecodeError as je:
                logs.append(log_message(f"JSON字符串解析失败: {je}", "ERROR"))
                raise
            except Exception as se:
                logs.append(log_message(f"字符串处理失败: {se}", "ERROR"))
                raise
        
        data_list = data_dict.get('data', [])
        template_path = data_dict.get('templatePath', '')
        output_path = data_dict.get('outputPath', '')
        
        # 检查data_list的类型和内容
        logs.append(log_message(f"data_list类型: {type(data_list)}"))
        # logs.append(log_message(f"data_list值: {data_list}"))
        
        # 确保data_list是列表类型
        if not isinstance(data_list, list):
            logs.append(log_message(f"警告: data_list不是列表类型，类型为: {type(data_list)}"))
            if isinstance(data_list, dict):
                data_list = [data_list]
            elif data_list is None:
                data_list = []
            else:
                return {
                    "success": False,
                    "error": f"数据格式错误: data_list应为列表类型，实际为: {type(data_list)}",
                    "logs": logs
                }
        
        logs.append(log_message(f"数据条数: {len(data_list)}"))
        logs.append(log_message(f"模板路径: {template_path}"))
        logs.append(log_message(f"输出路径: {output_path}"))
        
        if not data_list:
            return {
                "success": False,
                "error": "没有可处理的数据",
                "logs": logs
            }
        
        # 检查模板文件是否存在
        if template_path and not os.path.exists(template_path):
            return {
                "success": False,
                "error": f"模板文件不存在: {template_path}",
                "logs": logs
            }
        
        # 如果没有提供模板路径，创建一个默认模板
        if not template_path:
            logs.append(log_message("未提供模板路径，将创建默认模板"))
            doc = create_default_template()
        else:
            logs.append(log_message("加载Word模板..."))
            doc = Document(template_path)
        
        # 查找第一个表格
        if not doc.tables:
            logs.append(log_message("文档中没有表格，将创建新表格"))
            # 创建新表格
            table = doc.add_table(rows=1, cols=6)
            table.style = 'Table Grid'
            
            # 设置表头
            header_cells = table.rows[0].cells
            header_cells[0].text = '地区'  # region
            header_cells[1].text = '标准编号'  # standard
            header_cells[2].text = '标准名称'  # standardName
            header_cells[3].text = '发布日期'  # dateOfPublication
            header_cells[4].text = '摘要'  # brief
            header_cells[5].text = 'URL链接'  # url
            
            # 设置表头样式
            for i, cell in enumerate(header_cells):
                cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
                for run in cell.paragraphs[0].runs:
                    run.bold = True
                    # 第一列和最后一列设置橙色
                    if i == 0 or i == 5:
                        run.font.color.rgb = RGBColor(255, 165, 0)  # 橙色
                # 如果没有runs，创建新的run并设置样式
                if not cell.paragraphs[0].runs:
                    run = cell.paragraphs[0].add_run(cell.text)
                    run.bold = True
                    if i == 0 or i == 5:
                        run.font.color.rgb = RGBColor(255, 165, 0)  # 橙色
                    cell.text = ''  # 清空原文本，避免重复
        else:
            table = doc.tables[0]
            logs.append(log_message(f"找到表格，当前行数: {len(table.rows)}"))
        
        # 提取并处理数据
        logs.append(log_message("开始提取数据..."))
        source_type = data_dict.get('source', 'unknown')
        logs.append(log_message(f"调用extract_data_from_json前 - data_list类型: {type(data_list)}, 值: {data_list}"))
        logs.append(log_message(f"调用extract_data_from_json前 - source_type: {source_type}"))
        
        try:
            extracted_data = extract_data_from_json(data_list, source_type)
            logs.append(log_message(f"extract_data_from_json调用成功，返回类型: {type(extracted_data)}"))
        except Exception as e:
            logs.append(log_message(f"extract_data_from_json调用失败: {str(e)}"))
            return {
                "success": False,
                "error": f"数据提取失败: {str(e)}",
                "logs": logs
            }
        
        # 写入数据到表格
        logs.append(log_message("开始写入数据到表格..."))
        logs.append(log_message(f"extracted_data类型: {type(extracted_data)}"))
        logs.append(log_message(f"extracted_data值: {extracted_data}"))
        
        # 确保extracted_data是可迭代的列表
        if not isinstance(extracted_data, (list, tuple)):
            logs.append(log_message(f"错误: extracted_data不是可迭代对象，类型为: {type(extracted_data)}"))
            return {
                "success": False,
                "error": f"数据处理错误: extracted_data应为列表类型，实际为: {type(extracted_data)}",
                "logs": logs
            }
        
        rows_added = 0
        
        for item in extracted_data:
            # 添加新行
            row_cells = table.add_row().cells
            
            # 按照用户要求的列顺序填充数据：
            # 第一列：region，第二列：standard，第三列：standardName
            # 第四列：dateOfPublication，第五列：brief，第六列：url
            
            # 填充数据并设置颜色
            row_cells[0].text = str(item.get('region', ''))  # 第一列：region
            row_cells[1].text = str(item.get('standard', ''))  # 第二列：standard
            row_cells[2].text = str(item.get('standardName', ''))  # 第三列：standardName
            row_cells[3].text = str(item.get('dateOfPublication', ''))  # 第四列：dateOfPublication
            row_cells[4].text = str(item.get('brief', ''))  # 第五列：brief
            
            # 第六列：url - 创建超链接
            url_value = str(item.get('url', ''))
            if url_value and url_value.strip() and url_value.lower() not in ['', 'none', 'null']:
                # 清空原有内容
                row_cells[5].text = ''
                # 添加超链接，显示为简短的"链接"文字
                add_hyperlink(row_cells[5].paragraphs[0], url_value, '链接', '#FF6600')  # 使用橙色
            else:
                row_cells[5].text = ''  # 如果没有有效URL，显示"无链接"
            
            # 设置第一列和最后一列文本颜色为橙色并加粗
            # 第一列（地区）设置为橙色并加粗
            for run in row_cells[0].paragraphs[0].runs:
                run.font.color.rgb = RGBColor(255, 165, 0)  # 橙色
                run.bold = True  # 加粗
            if not row_cells[0].paragraphs[0].runs:
                run = row_cells[0].paragraphs[0].add_run(row_cells[0].text)
                run.font.color.rgb = RGBColor(255, 165, 0)  # 橙色
                run.bold = True  # 加粗
                row_cells[0].text = ''  # 清空原文本，避免重复
            
            # 最后一列（URL链接）- 如果不是超链接则设置为橙色并加粗
            if not url_value or not url_value.strip() or url_value.lower() in ['', 'none', 'null']:
                # 只有当URL无效时才应用橙色加粗样式
                for run in row_cells[5].paragraphs[0].runs:
                    run.font.color.rgb = RGBColor(255, 165, 0)  # 橙色
                    run.bold = True  # 加粗
                if not row_cells[5].paragraphs[0].runs:
                    run = row_cells[5].paragraphs[0].add_run(row_cells[5].text)
                    run.font.color.rgb = RGBColor(255, 165, 0)  # 橙色
                    run.bold = True  # 加粗
                    row_cells[5].text = ''  # 清空原文本，避免重复
            
            rows_added += 1
            
            if rows_added % 10 == 0:
                logs.append(log_message(f"已处理 {rows_added} 条数据..."))
        
        logs.append(log_message(f"数据写入完成，共添加 {rows_added} 行"))
        
        # 确定输出文件路径
        if not output_path:
            # 如果没有指定输出路径，使用桌面目录
            output_path = os.path.join(os.path.expanduser('~'), 'Desktop')
        
        # 确保输出路径存在
        os.makedirs(output_path, exist_ok=True)
        
        # 生成输出文件名
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        output_filename = f"technical_update_report_{timestamp}.docx"
        output_file_path = os.path.join(output_path, output_filename)
        
        # 保存文档
        logs.append(log_message(f"保存文档到: {output_file_path}"))
        doc.save(output_file_path)
        
        logs.append(log_message("技术更新报告生成完成！"))
        
        return {
            "success": True,
            "output_file": output_file_path,
            "rows_added": rows_added,
            "message": f"成功生成技术更新报告，共处理 {rows_added} 条数据",
            "logs": logs
        }
        
    except json.JSONDecodeError as e:
        error_msg = f"JSON解析错误: {str(e)}"
        logs.append(log_message(error_msg, "ERROR"))
        return {
            "success": False,
            "error": error_msg,
            "logs": logs
        }
    except Exception as e:
        error_msg = f"处理过程中发生错误: {str(e)}"
        logs.append(log_message(error_msg, "ERROR"))
        return {
            "success": False,
            "error": error_msg,
            "logs": logs
        }

def create_default_template():
    """
    创建默认的Word模板
    
    Returns:
        Document: Word文档对象
    """
    doc = Document()
    
    # 添加标题
    title = doc.add_heading('技术更新报告', 0)
    title.alignment = WD_ALIGN_PARAGRAPH.CENTER
    
    # 添加日期
    date_para = doc.add_paragraph(f'生成日期: {datetime.now().strftime("%Y年%m月%d日")}')
    date_para.alignment = WD_ALIGN_PARAGRAPH.CENTER
    
    # 添加空行
    doc.add_paragraph()
    
    # 添加说明
    doc.add_paragraph('本报告汇总了各个数据源的技术更新信息：')
    
    # 添加表格
    table = doc.add_table(rows=1, cols=6)
    table.style = 'Table Grid'
    
    # 设置表头
    header_cells = table.rows[0].cells
    header_cells[0].text = '地区'  # region
    header_cells[1].text = '标准编号'  # standard
    header_cells[2].text = '标准名称'  # standardName
    header_cells[3].text = '发布日期'  # dateOfPublication
    header_cells[4].text = '摘要'  # brief
    header_cells[5].text = 'URL链接'  # url
    
    # 设置表头样式
    for i, cell in enumerate(header_cells):
        cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        for run in cell.paragraphs[0].runs:
            run.bold = True
            # 第一列和最后一列设置橙色
            if i == 0 or i == 5:
                run.font.color.rgb = RGBColor(255, 165, 0)  # 橙色
        # 如果没有runs，创建新的run并设置样式
        if not cell.paragraphs[0].runs:
            run = cell.paragraphs[0].add_run(cell.text)
            run.bold = True
            if i == 0 or i == 5:
                run.font.color.rgb = RGBColor(255, 165, 0)  # 橙色
            cell.text = ''  # 清空原文本，避免重复
    
    return doc

def extract_data_from_json(json_data, source_type):
    """
    从JSON数据中提取需要的字段
    """
    # 这个函数内部的日志会通过stderr输出，不需要返回
    log_message(f"extract_data_from_json开始 - json_data类型: {type(json_data)}, 值: {json_data}")
    log_message(f"extract_data_from_json开始 - source_type: {source_type}")
    
    extracted_data = []
    
    # 检查json_data的类型
    if not isinstance(json_data, (list, tuple)):
        log_message(f"警告: json_data不是可迭代对象，类型为: {type(json_data)}, 值为: {json_data}")
        if isinstance(json_data, dict):
            # 如果是字典，包装成列表
            log_message("json_data是字典类型，包装成列表")
            json_data = [json_data]
        elif isinstance(json_data, int):
            # 如果是整数，这是错误的情况
            log_message(f"错误: json_data是整数类型: {json_data}，这不应该发生")
            return []
        else:
            # 如果是其他类型，返回空列表
            log_message(f"错误: 无法处理的数据类型: {type(json_data)}")
            return []
    else:
        log_message("json_data是可迭代类型，直接使用")
    
    for item in json_data:
        # 确保item是字典类型
        if isinstance(item, dict):
            # 为每个数据项添加source标识
            item['source'] = source_type
            extracted_data.append(item)
        else:
            log_message(f"警告: 跳过非字典类型的数据项: {type(item)}, 值为: {item}")
    
    log_message(f"extract_data_from_json返回数据类型: {type(extracted_data)}")
    log_message(f"extract_data_from_json返回数据长度: {len(extracted_data) if isinstance(extracted_data, (list, tuple)) else 'N/A'}")
    
    # 确保返回的是列表类型
    if not isinstance(extracted_data, list):
        log_message(f"警告: extract_data_from_json返回了非列表类型: {type(extracted_data)}")
        return []
    
    return extracted_data

def main():
    """
    主函数
    """
    # 清理stdout缓冲区，确保没有残留输出
    sys.stdout.flush()
    
    # 设置输出编码为UTF-8
    try:
        if hasattr(sys.stdout, 'reconfigure') and sys.stdout.encoding != 'utf-8':
            sys.stdout.reconfigure(encoding='utf-8')
        if hasattr(sys.stderr, 'reconfigure') and sys.stderr.encoding != 'utf-8':
            sys.stderr.reconfigure(encoding='utf-8')
    except Exception as e:
        # 如果重新配置失败，继续执行，不影响主要功能
        print(f"编码配置警告: {e}", file=sys.stderr)
    
    try:
        if len(sys.argv) < 2:
            result = {
                "success": False,
                "error": "缺少必要的参数"
            }
        else:
            data_input = sys.argv[1]
            result = process_tech_update_data(data_input)
        
        # 确保stdout是干净的，没有其他输出
        sys.stdout.flush()
        
        # 输出结果，确保中文字符正确编码
        output = json.dumps(result, ensure_ascii=False, indent=2)
        # 使用一次性写入，避免多次print可能导致的问题
        sys.stdout.write(output + '\n')
        sys.stdout.flush()
        
    except Exception as e:
        error_result = {
            "success": False,
            "error": f"脚本执行错误: {str(e)}"
        }
        output = json.dumps(error_result, ensure_ascii=False, indent=2)
        sys.stdout.write(output + '\n')
        sys.stdout.flush()
        sys.exit(1)

if __name__ == "__main__":
    main()